﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using GraphosData;
using System.Windows.Media.Animation;

namespace GraphosControls
{
    /// <summary>
    /// Interaction logic for SearchViewer.xaml
    /// </summary>
    public partial class SearchViewer : UserControl
    {
        private SearchEngine mySearch;
        private Node meantNode = null;
        private List<object> list = null;

        public SearchViewer()
        {
            InitializeComponent();
            DataContext = this;
            MainListBox.SelectionChanged += new SelectionChangedEventHandler(MainListBox_SelectionChanged);
            SizeChanged += new SizeChangedEventHandler(SearchViewer_SizeChanged);
        }



        void SearchViewer_SizeChanged(object sender, SizeChangedEventArgs e)
        {
            if (MainListBox.Items.Count > 0)
                (sender as SearchViewer).RaiseEvent(new RoutedEventArgs(ExpanderPanel.MainContentSizeChangedEvent));
        }

        public IList<Node> SearchResults
        {
            get { return (IList<Node>)GetValue(SearchResultsProperty); }
            set { SetValue(SearchResultsProperty, value); }
        }
        public static readonly DependencyProperty SearchResultsProperty =
            DependencyProperty.Register("SearchResults", typeof(IList<Node>), typeof(SearchViewer), new UIPropertyMetadata(new List<Node>()));

        public Node SelectedResult
        {
            get { return (Node)GetValue(SelectedResultProperty); }
            set { SetValue(SelectedResultProperty, value); }
        }
        public static readonly DependencyProperty SelectedResultProperty =
            DependencyProperty.Register("SelectedResult", typeof(Node), typeof(SearchViewer), new UIPropertyMetadata(null, new PropertyChangedCallback(OnSelectedResultChanged)));
        private static void OnSelectedResultChanged(DependencyObject sender, DependencyPropertyChangedEventArgs args)
        {
            SearchViewer viewer = sender as SearchViewer;
            if (viewer.MainListBox.Items.Contains(viewer.SelectedResult))
            {
                viewer.MainListBox.SelectedItem = viewer.SelectedResult;
            }
            else
            {
                viewer.MainListBox.SelectedIndex = -1;
            }
        }


        public string CurrentSearchQuery
        {
            get { return (string)GetValue(CurrentSearchQueryProperty); }
            set { SetValue(CurrentSearchQueryProperty, value); }
        }

        // Using a DependencyProperty as the backing store for CurrentSearchQuery.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty CurrentSearchQueryProperty =
            DependencyProperty.Register("CurrentSearchQuery", typeof(string), typeof(SearchViewer), new UIPropertyMetadata(string.Empty, new PropertyChangedCallback(OnCurrentSearchQueryChanged)));

        private static void OnCurrentSearchQueryChanged(DependencyObject sender, DependencyPropertyChangedEventArgs args)
        {
            SearchViewer viewer = sender as SearchViewer;
            viewer.Search();
            viewer.RaiseEvent(new RoutedEventArgs(ExpanderPanel.MainContentSizeChangedEvent));
        }

        public string DidYouMean
        {
            get { return (string)GetValue(DidYouMeanProperty); }
            set { SetValue(DidYouMeanProperty, value); }
        }
        public static readonly DependencyProperty DidYouMeanProperty =
            DependencyProperty.Register("DidYouMean", typeof(string), typeof(SearchViewer), new UIPropertyMetadata(null));

        public IList<Node> AllPossibleValues
        {
            get { return (IList<Node>)GetValue(AllPossibleValuesProperty); }
            set { SetValue(AllPossibleValuesProperty, value); }
        }
        public static readonly DependencyProperty AllPossibleValuesProperty =
            DependencyProperty.Register("AllPossibleValues", typeof(IList<Node>), typeof(SearchViewer), new FrameworkPropertyMetadata(
                new List<Node>(), FrameworkPropertyMetadataOptions.AffectsRender, new PropertyChangedCallback(OnAllPossibleValuesChanged)));
        private static void OnAllPossibleValuesChanged(DependencyObject sender, DependencyPropertyChangedEventArgs args)
        {
            SearchViewer viewer = sender as SearchViewer;
            viewer.mySearch = new SearchEngine((IList<Node>)args.NewValue);
        }
        /// <summary>
        /// Do a search on the current data in the object using strFind as the search term
        /// </summary>
        /// <param name="strFind">The string to search for</param>
        public void Search()
        {
            list = new List<object>();
            MainListBox.ItemsSource = list;

            List<Node> results = mySearch.Search(CurrentSearchQuery);

            meantNode = mySearch.PartialMatch;
            if (meantNode != null)
            {
                if(results.Count == 0 ||
                   results.ElementAt<Node>(0).Person.FirstName != meantNode.Person.FirstName)
                {
                    Button b = new Button();
                    b.Style = (Style)TryFindResource("SearchButtonStyle");
                    b.Content = "Did you mean: " + meantNode.Person.FirstName;
                    b.Foreground = Brushes.White;
                    b.Click += new RoutedEventHandler(b_Click);
                    list.Add(b);
                }
            }

            if (results != null)
            {
                foreach (Node n in results)
                {
                    list.Add(n);
                }
            }
        }

        private void b_Click(object sender, RoutedEventArgs e)
        {
            list.Add(meantNode);
            MainListBox.SelectedItem = meantNode;
        }

        protected override void OnPreviewKeyDown(KeyEventArgs e)
        {
            if (MainListBox.Items.Count == 0)
                return;

            if (e.Key == Key.Enter)
            {
                if (m_highlightIndex == -1)
                    MainListBox.SelectedIndex = 0;

                MainListBox.SelectedIndex = m_highlightIndex;

                MainTextBox.Focus();
            }
            else
            {
                if (!MainTextBox.IsFocused)
                    MainTextBox.Focus();

                if (e.Key == Key.Down || e.Key == Key.Up)
                {
                    int inc = e.Key == Key.Down ? 1 : -1;
                    if ((m_highlightIndex == 0 && e.Key == Key.Up) || (m_highlightIndex == MainListBox.Items.Count - 1 && e.Key == Key.Down))
                    {
                        m_highlightIndex = -1;
                    }
                    else
                    {
                        int next;
                        if (m_highlightIndex == -1 && e.Key == Key.Up)
                            next = MainListBox.Items.Count - 1;
                        else if (m_highlightIndex == -1 && e.Key == Key.Down)
                            next = 0;
                        else
                            next = (m_highlightIndex + inc + MainListBox.Items.Count) % MainListBox.Items.Count;


                        ListBoxItem item = MainListBox.ItemContainerGenerator.ContainerFromIndex(next) as ListBoxItem;
                        if (item != null)
                        {
                            if (item.Focus())
                            {
                                m_highlightIndex = next;
                            }
                        }
                    }
                    e.Handled = true;
                }
                else
                {
                    m_highlightIndex = -1;
                }
            }
            base.OnPreviewKeyDown(e);
        }






        protected override void OnGotFocus(RoutedEventArgs e)
        {
            base.OnGotFocus(e);
            if (!MainTextBox.IsFocused)
            {
                MainTextBox.Focus();
            }
        }
        private void MainListBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            BindingExpression exp = MainListBox.GetBindingExpression(ListBox.SelectedItemProperty);
            exp.UpdateSource();
            if (MainListBox.SelectedItem != null &&
                MainListBox.SelectedItem.GetType() == typeof(Button))
            {
                b_Click(null, null);
            }


            m_highlightIndex = MainListBox.SelectedIndex;
            MainTextBox.Focus();
        }

        private int m_highlightIndex = -1;

    }
}
